/****************** 类和对象 上 ******************/
#include<iostream>
#include<cstdlib>
using namespace std;


#if 0

#include<iostream>
#include<cstdlib>
#include<stdio.h>
#include<stdlib.h>


typedef int T;
struct Stack
{
    T* arr;
    int top;        // 栈顶
    int capacity;   // 总容量
};

void Init(Stack* st){
    st->arr = (T*)malloc(sizeof(T) * 100);
    st->top = 0, st->capacity = 100;
}
T Top(Stack* st)
{
	return st->arr[st->top - 1];
}
void Push(Stack* st, T x){
    // 空间满了扩容
    if(st->top == st->capacity)
    {
        st->arr = (T*)realloc(st->arr, sizeof(T) * st->capacity * 2);
        st->capacity *= 2;
    }
    st->arr[st->top++] = x;
}
void Pop(Stack* st){
    st->top--;
}
bool Empty(Stack* st){
    return st->top == 0;
}

int main()
{
    Stack st;
    Init(&st);   
    Push(&st, 1);
    // ...
    return 0;
}

// C语言的结构体里面只有变量
// C++进行了升级，结构体里面还可以有函数
// C++升级
#include<stdio.h>
#include<stdlib.h>
typedef int T;
struct Stack
{
// Init、Push、Pop、Empty都为成员函数
    void Init(){
        arr = (T*)malloc(sizeof(T) * 100);
        top = 0, capacity = 100;
    }
    void Push(T x){
        // 空间满了扩容
        if(top == capacity)
        {
            arr = (T*)realloc(arr, sizeof(T) * capacity * 2);
            capacity *= 2;
        }
        arr[top++] = x;
    }
    void Pop(Stack* st){
        top--;
    }
    bool Empty(Stack* st){
        return top == 0;
    }
// arr、top、capacity都为成员变量
    T* arr;
    int top;        // 栈顶
    int capacity;   // 总容量
};

int main()
{
    Stack st;
    st.Init();   // 访问成员函数（或成员变量）都用.（指针用->）
    st.Push(1);
    return 0;
}


// C++中更喜欢用class，还引入了访问限定符public、private、protected (学继承前可以认为private与protected没什么区别)
/*
1.public 修饰的成员可以在类外面直接访问，private 修饰的成员不可以在类外面直接访问
2.访问权限的作用域是：该访问限定符到下一个访问限定符之间（没有下一个访问限定符就是该访问限定符到类的末尾）
3.class默认访问权限是private，struct默认访问权限是public
*/

class A // C++更喜欢用class
{
public: // 从此行到private之间的成员的访问权限都是public
    int a1;
    char c1;
    void func1() { 
        puts("void func1()"); 
        // printf("a1:%d c1:%c a2: %d c2: %c\n", a1, c1, a2, c2); // 类内部可访问所有成员
    }

private: // 从此行到类结尾的成员的访问权限都是private
    int a2;
    char c2;
    void func2() { 
        puts("void func2()"); 
        printf("a1:%d c1:%c a2: %d c2: %c\n", a1, c1, a2, c2);
    }
};

int main()
{
    A t1;
    // a1、c1、func1 可以在结构体外访问
    t1.a1 = 1;
    t1.c1 = 'a';
    printf("%d %c\n", t1.a1, t1.c1);
    t1.func1(); // 调用时未初始化a2、c2，打印出来可能是乱码
    A::func1();

    // // a2、c2、func2 不可以在结构体外访问
    // t1.a2 = 2;
    // t1.c2 = 'z';
    // t1.func2();
    return 0;
}



class Stack
{
public:
    void init(int n);
private:
    int* _arr;
    int _top;
    int _capacity;
};

void Stack::init(int n)
{
    _arr = (int*)malloc(sizeof(int) * n);
    _top = 0;
    _capacity = n;
}

int main()
{
    // cout << sizeof(Stack) << endl;
    // Stack st1;
    // cout << sizeof(st1) << endl;
    cout << sizeof(int*);
    return 0;
}


typedef int T;
class Stack
{
public:
    void Init(){
        arr = (T*)malloc(sizeof(T) * 100);
        top = 0, capacity = 100;
    }
    T Top()
	{
		return arr[top - 1];
	}
    void Push(T x){
        if(top == capacity)
        {
            arr = (T*)realloc(arr, sizeof(T) * capacity * 2);
            capacity *= 2;
        }
        arr[top++] = x;
    }
    void Pop(){
        top--;
    }
    bool Empty(){
        return top == 0;
    }
private:
    T* arr;
    int top;        // 栈顶
    int capacity;   // 总容量
};
int main()
{
    // 变量跟函数封装一起，但计算类的大小只会计算成员变量，函数是公共的
    // 类的大小遵循C语言结构体对齐的规则 // 设置默认对其数：#pragma pack(1)
    cout << sizeof(Stack) << endl;  // 你可以删除一个成员函数，可以发现输出结果不变

    Stack st1, st2;
    cout << sizeof(st1) << endl;
    cout << sizeof(st2) << endl;

    st1.Init();
    st1.Push(1);

    st2.Init();  // 通过汇编可以看出st1与st2调用的是同一个Init() 
    st2.Push(2);
    return 0;
}

class A
{};
class B
{
public:
    void func()
    {}
};
int main()
{
    cout << sizeof(A) << endl;
    cout << sizeof(B) << endl;
    return 0;
}

/*************** this *****************/

class Date
{
public:
    void init(int y, int m, int d)
    {
        _year = y;
        _month = m;
        _day = d;
    }

    void Print()
    {
        printf("%d-%d-%d\n", _year, _month, _day);
        printf("%d-%d-%d\n", this->_year, this->_month, this->_day);
        // this = nullptr;
    }

private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    Date d1;
    d1.init(2025, 9, 9); // 编译器处理后的代码：d1.init(&d1, 2025, 9, 9);  会将d1的地址传给this
    d1.Print();          // 编译器处理后的代码：d1.Print(&d1);  

    Date* p = &d1;
    p->init(2026, 9, 10);// 指针调用会处理成：p->init(p, 2026, 9, 10);
    p->Print();          // 编译器处理后的代码：p->Print(p);
    return 0;
}
#endif

#if 1
class A
{
public:
    void Print()
    {
        cout << _a << endl;
    }

private:
    int _a;
};

int main()
{
    A* p = nullptr;
    p->Print();
    cout << A::();
    return 0;
}

#endif